﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace X3DLib
{
    public class CTree
    {
        private int maxNum;
        //以下是背景设的RGB
        private double x1, x2;
        private double y1, y2;
        private double z1, z2;
        private double l, s;                  //l，s分别为为树干长度和粗细系数
        private double wt, wl;                //wt,wl分别为树枝与父干夹角、树叶与父干夹角
        private int n;                       //n叉树
        private int m;                       //每根树枝上有m片叶子
        private double ls;                   //树叶大小比例ls
        private double[] c;
        private double[] t;
        private double[] h;
        private double[] r;
        private string[] g;
        private double[] w;                 //树干绕Y轴旋转角度
        private string[] T;
        private string Tmax;
        private string Trunk;               //生成树干Trunk

        //获取整个文档结构
        public string getStructure(string scene)
        {
            return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
                    + "<!DOCTYPE X3D PUBLIC \"ISO//Web3D//DTD X3D 3.2//EN\" \"http://www.web3d.org/specifications/x3d-3.2.dtd\">\n"
                    + "<X3D profile='Immersive' version='3.2' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation='http://www.web3d.org/specifications/x3d-3.2.xsd'>"
                    + "<head>\n" + "<meta content='*enter FileNameWithNoAbbreviations.x3d here*' name='title'/>\n"
                    + "<meta content='*enter description here, short-sentence summaries preferred*' name='description'/>\n"
                    + "<meta content='*enter name of original author here*' name='creator'/>\n"
                    + "<meta content='*enter name of original author here*' name='creator'/>\n"
                    + "<meta content='*if manually translating VRML-to-X3D, enter name of person translating here*' name='translator'/>\n" + "<meta content='*enter date of initial version here*' name='created'/>\n"
                    + "<meta content='*enter date of translation here*' name='translated'/>\n"
                    + "<meta content='*enter date of latest revision here*' name='modified'/>\n"
                    + "<meta content='*enter version here, if any*' name='version'/>\n"
                    + "<meta content='*enter reference citation or relative/online url here*' name='reference'/>\n"
                    + "<meta content='*enter additional url/bibliographic reference information here*' name='reference'/>\n"
                    + "<meta content='*enter reference resource here if required to support function, delivery, or coherence of content*' name='requires'/>\n"
                    + "<meta content='*enter copyright information here* Example: Copyright (c) Web3D Consortium Inc. 2008' name='rights'/>\n"
                    + "<meta content='*enter drawing filename/url here*' name='drawing'/>\n"
                    + "<meta content='*enter image filename/url here*' name='image'/>\n"
                    + "<meta content='*enter movie filename/url here*' name='MovingImage'/>\n"
                    + "<meta content='*enter photo filename/url here*' name='photo'/>\n"
                    + "<meta content='*enter subject keywords here*' name='subject'/>\n"
                    + "<meta content='*enter permission statements or url here*' name='accessRights'/>\n"
                    + "<meta content='*insert any known warnings, bugs or errors here*' name='warning'/>\n"
                    + "<meta content='*enter online Uniform Resource Identifier (URI) or Uniform Resource Locator (URL) address for this file here*' name='identifier'/>\n"
                    + "<meta content='X3D-Edit, https://savage.nps.edu/X3D-Edit' name='generator'/>\n"
                    + "<meta content='../../license.html' name='license'/>\n"
                    + "</head>\n"
                    + scene
                    + "</X3D>\n";
        }

        //设置递归次数 maxNum
        public void setRecurNum(int maxNum)
        {
            this.maxNum = maxNum;
            c = new double[maxNum];
            t = new double[maxNum];
            h = new double[maxNum];
            r = new double[maxNum];
            g = new string[maxNum];
        }

        //设置背景颜色
        public void setBackground(double x1, double y1, double z1)
        {
            this.x1 = x1;
            this.y1 = y1;
            this.z1 = z1;
        }

        //获取背景颜色，由getScene调用
        private string getBackground()
        {
            return "<Background skyColor='" + x1 + " " + y1 + " " + z1 + "'/>\n";
        }

        //获得scene
        public string getScene(string transform)
        {
            return "<Scene>\n" + this.getBackground() + transform + "</Scene>\n";
        }

        //设置树叶颜色
        public void setLeafColor(double x2, double y2, double z2)
        {
            this.x2 = x2;
            this.y2 = y2;
            this.z2 = z2;
        }

        //设置树枝的长度系数l、粗细系数s
        public void setTrunkSize(double l, double s)
        {
            this.l = l;
            this.s = s;
        }

        //设置树叶与父枝夹角wl、树枝与父枝夹角wt
        public void setAngle(double wl, double wt)
        {
            this.wt = wt;
            this.wl = wl;
        }

        //设置n叉树
        public void setTreeModel(int n)
        {
            this.n = n;
            w = new double[n];
            T = new string[n];
        }

        //设置每个树枝上有m片叶子
        public void setLeafModel(int m)
        {
            this.m = m;
        }

        //设置叶子大小比例系数
        public void setLeafSize(double ls)
        {
            this.ls = ls;
        }

        public string getTree()
        {
            c[0] = -0.2;
            h[0] = 0.2;
            t[0] = -0.1;
            r[0] = 0.01;

            for (int i = 1; i < maxNum; i++)
            {
                h[i] = l * h[i - 1];
                r[i] = s * r[i - 1];
                if (i == 1)
                {
                    t[1] = -h[i - 1] * ls - h[i] / 2;
                    c[1] = c[i - 1] * ls - h[i];
                }
                else
                {
                    t[i] = t[i - 1] - h[i - 1] / 2 - h[i] / 2;
                    c[i] = c[i - 1] - h[i];
                }
            }

            for (int j = 0; j < maxNum; j++)
            {
                Tmax = null;
                Trunk = "<Transform  translation='0 " + t[j] + " 0'>\n"
                        + "<Shape>\n"
                        + "<Appearance>\n"
                        + "       <Material diffuseColor='0.7 0.5 0.3'/>\n"
                        + "    </Appearance>\n"
                        + "    <Cylinder radius='" + r[j]
                        + "' height='" + h[j] + "'/>\n"
                        + "</Shape>\n" + "</Transform>\n" + "</Transform>\n" + "\n";
                for (int a = 0; a < n; a++)
                {
                    w[a] = (6.282 / n) * (a + 1);
                    T[a] = "<Transform  rotation='0 1 0 " + w[a] + "' >\n" + "<Shape USE='G" + (j - 1) + "'/>\n"
                            + "</Transform>\n" + "\n";
                    Tmax += T[a];
                }

                if (j == 0)
                {
                    g[0] = "<Transform DEF='G" + j
                            + "' scale='" + ls + " " + ls + " " + ls + "'>\n"
                            + "<Transform scale='0.5 1 0.05'  rotation='1 0 0 " + wl
                            + "' center='0 " + c[j] + " 0' >\n"
                            + "<Shape>\n" + "<Appearance>\n"
                            + "<Material diffuseColor='" + x2 + " " + y2 + " " + z2 + "'/>\n"
                            + "</Appearance>\n" + "<Sphere radius='0.2'/>\n" + "</Shape>\n" + "</Transform>\n"
                            + "</Transform>\n";
                }
                else if (j == 1)
                {
                    Tmax = null;
                    for (int a = 0; a < m; a++)
                    {
                        w[a] = (6.282 / m) * (a + 1);
                        T[a] = "<Transform  rotation='0 1 0 " + w[a] + "' >\n"
                                + "<Shape USE='G" + (j - 1) + "'/>\n"
                                + "</Transform>\n" + "\n";

                        Tmax += T[a];
                    }
                    g[j] = "<Transform  DEF='G" + j + "' rotation='1 0 0 " + wt
                            + "' center='0 " + c[j] + " 0' >\n" + g[j - 1] + Tmax + Trunk;
                }
                else if (maxNum > 1 && j == maxNum - 1)
                {
                    g[j] = g[j - 1] + Tmax + "<Transform  translation='0 " + t[j] + " 0'>\n"
                            + "<Shape>\n" + "<Appearance>\n"
                            + "       <Material diffuseColor='0.7 0.5 0.3'/>\n"
                            + "    </Appearance>\n"
                            + "    <Cylinder radius='" + r[j] + "' height='" + h[j] + "'/>\n"
                            + "</Shape>\n" + "</Transform>\n" + "\n";
                }
                else
                {
                    g[j] = "<Transform  DEF='G" + j + "' rotation='1 0 0 " + wt
                            + "' center='0 " + c[j] + " 0' >\n" + g[j - 1] + Tmax + Trunk;
                }
            }
            return g[maxNum - 1];
        }

        public CTree()
        {
            //tree.setRecurNum(6);
            this.setRecurNum(4);
            this.setBackground(0.98, 0.98, 0.98);
            this.setLeafColor(0, 1, 0);
            this.setTrunkSize(1.6, 1.6);
            this.setAngle(0.785, 0.785);
            this.setTreeModel(4);
            this.setLeafModel(3);
            this.setLeafSize(0.5);
        }

        public string toString()
        {
            return this.getStructure(this.getScene(this.getTree()));
        }

        //    public static void main(string[] argv)
        //    {
        //        HeTree tree = new HeTree();
        ////        tree.setRecurNum(6);
        //        tree.setRecurNum(4);
        //        tree.setBackground(0.98, 0.98, 0.98);
        //        tree.setLeafColor(0, 1, 0);
        //        tree.setTrunkSize(1.6, 1.6);
        //        tree.setAngle(0.785, 0.785);
        //        tree.setTreeModel(4);
        //        tree.setLeafModel(3);
        //        tree.setLeafSize(0.5);
        //        string transforms = tree.getTree();
        //        string a = tree.getStructure(tree.getScene(transforms));
        //        try
        //        {
        ////			File file = new File("D:/tree2010/100330/hechou.x3d");
        //            File file = new File("D:/dom4j/hechou.x3d");
        //            FileWriter fileWriter = new FileWriter(file);
        //            BufferedWriter buf = new BufferedWriter(fileWriter);
        //            buf.write(a);
        //            buf.close();
        //            fileWriter.close();
        //        } catch (IOException e)
        //        {
        //            // TODO Auto-generated catch block
        //            e.printStackTrace();
        //        }
        //    }
    }
}
